﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data;
using ShivamEMR.Model.DataInterfaces;
using System.Data.Entity;
using ShivamEMR.Model.Domain.UserDomain;
using ShivamEMR.Model.Domain;


namespace ShivamEMR.Data.Repository
{
    public abstract class Repository<TObject> : IRepository<TObject>
        where TObject : class
    {
         
        protected Context Context = null;
        public Repository()
        {
            if (Context == null)
                Context = new Context();
        }

        public Repository(Context context)
        {
            Context = context;
        }

       

        public virtual void SaveChanges()
        {
            Context.SaveChanges();
        }
        protected DbSet<TObject> DbSet
        {
            get
            {
                return Context.Set<TObject>();
            }
        }

        public virtual IQueryable<TObject> GetAll()
        {
            return DbSet.AsQueryable();
        }

        public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.Where(predicate).AsQueryable<TObject>();
        }

        public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter, out int total, int index = 0, int size = 50)
        {
            int skipCount = index * size;
            var _resetSet = filter != null ? DbSet.Where(filter).AsQueryable() : DbSet.AsQueryable();
            _resetSet = skipCount == 0 ? _resetSet.Take(size) : _resetSet.Skip(skipCount).Take(size);
            total = _resetSet.Count();
            return _resetSet.AsQueryable();
        }

        public bool Contains(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.Count(predicate) > 0;
        }

        public virtual TObject Find(params object[] keys)
        {
            return DbSet.Find(keys);
        }

        public virtual TObject Find(Expression<Func<TObject, bool>> predicate)
        {
            return DbSet.FirstOrDefault(predicate);
        }

        public virtual TObject Create(TObject TObject)
        {
            var newEntry = DbSet.Add(TObject);           
            return newEntry;
        }

        public virtual int Count
        {
            get
            {
                return DbSet.Count();
            }
        }

        public virtual void Delete(TObject TObject)
        {
            DbSet.Remove(TObject);
        }

        public virtual void Update(TObject TObject)
        {
            var entry = Context.Entry(TObject);
            DbSet.Attach(TObject);
            entry.State = EntityState.Modified;
        }

        public virtual void Delete(Expression<Func<TObject, bool>> predicate)
        {
            var objects = Filter(predicate);
            foreach (var obj in objects)
                DbSet.Remove(obj);
        }
        

        public IQueryable<TObject> All
        {
            get { return DbSet.AsQueryable(); }
        }


        public void Save()
        {
            Context.SaveChanges();
        }

        public bool Exists(TObject entity)
        {
            return DbSet.Local.Any(e => e == entity);
            //return DbSet.Any(e => e == entity);
        }


        public void InsertOrUpdate(TObject t)
        {            
            if (Exists(t))
            {
                var entry = Context.Entry(t);
                DbSet.Attach(t);
                entry.State = EntityState.Modified;
            }
            else
                DbSet.Add(t);   

        }


       
    }
}
